import { useEffect, useMemo, useRef, useState } from 'react'
import { useDebounceFn, useMemoizedFn, useUpdate } from 'ahooks'
import { Button, Checkbox, Input, Modal, Select, Space } from 'antd'

import { AgGridReact, CusAgGrid, ICusAgGridProps } from '@/components/CusAgGrid'
import { useChannels } from '@oBiz/hooks/SWRApi/useChannels'
import { getFirstLineName } from '../../utils'
import { popupSlot } from '../utils'
import { Cell } from './components'
import { IChannelListItem, TCol } from './interface'
import { useCommonCols } from './useCommonCols'
import { validateRow } from './utils'
import styles from './styles.module.less'

const updatePopup = popupSlot.insert(null)

interface IAddChannelModalProps {
  initialSelectRows: IChannelListItem[]
  onChange: (selectRows: IChannelListItem[]) => void
}

export const AddChannelModal = Object.assign(
  ({ initialSelectRows, onChange, destroy }: IAddChannelModalProps & { destroy: () => void }) => {
    const { open, onHide, afterOpenChange } = popupSlot.useAntdPopupAnimation(destroy)

    const [gridReadyFlag, setGridReadyFlag] = useState(false)
    const [isValid, setIsValid] = useState(false)
    const [selectedLen, setSelectedLen] = useState(0)
    const [errorLen, setErrorLen] = useState(0)
    const filterValueRef = useRef({
      channelName: '',
      firstLine: null as number | null,
      onlySelected: false,
    })
    const update = useUpdate()
    const gridRef = useRef<AgGridReact<IChannelListItem>>(null)

    const initialSelectRowsRef = useRef(initialSelectRows)
    const commonCols = useCommonCols(true)

    const validate = () => {
      const selectedRows = gridRef.current?.api.getSelectedRows() || []
      const errorRows = selectedRows.filter(row => !validateRow(row))
      setIsValid(selectedRows.length ? !errorRows.length : false)
      setSelectedLen(selectedRows.length)
      setErrorLen(errorRows.length)
    }

    // 列配置
    const defaultColDef = useMemo<Partial<TCol>>(
      () => ({
        flex: 1,
        minWidth: 180,
        sortable: false,
        mainMenuItems: ['autoSizeThis', 'autoSizeAll', 'separator', 'resetColumns'],
        cellRenderer: Cell,
        cellClassRules: {
          [styles.is_error]: ({ colDef, data, node }) => {
            if (!colDef.editable) return false
            return !!node.isSelected() && !validateRow(data)
          },
          [styles.is_readonly]: ({ colDef }) => !colDef.editable,
        },
      }),
      [],
    )
    const columnDefs = useMemo(
      () => [
        ...commonCols,
        {
          field: 'keepDate',
          headerName: '持续时间(h)',
          flex: 0.01,
          width: 150,
          minWidth: 150,
          pinned: 'right',
          editable: true,
        } satisfies TCol<'keepDate'>,
      ],
      [commonCols],
    )

    // 行勾选
    const rowSelection = useMemo<ICusAgGridProps<IChannelListItem>['rowSelection']>(() => {
      return { mode: 'multiRow', selectAll: 'filtered' }
    }, [])
    const onRowSelected = useMemoizedFn<NonNullable<ICusAgGridProps<IChannelListItem>['onRowSelected']>>(() => {
      gridRef.current?.api.refreshCells() // 触发 defaultColDef.cellClassRules 进行校验反馈
      validate() // 触发校验
    })

    // 拖动填充
    const cellSelection = useMemo<ICusAgGridProps<IChannelListItem>['cellSelection']>(
      () => ({
        handle: {
          mode: 'fill',
          direction: 'y',
          suppressClearOnFillReduction: true,
        },
      }),
      [],
    )

    // 值变更
    const onCellValueChanged = useMemoizedFn<NonNullable<ICusAgGridProps<IChannelListItem>['onCellValueChanged']>>(
      ({ colDef, newValue, oldValue, node }) => {
        if (!colDef.field) return
        oldValue = oldValue?.trim() || '' // oldValue 可能为 null
        newValue = newValue?.trim() || '' // newValue 可能为 null
        if (newValue !== oldValue) {
          node.setDataValue(colDef.field, newValue)
        }
        validate() // 触发校验
      },
    )

    // 本地搜索
    const handleFilter = () => gridRef.current!.api.onFilterChanged()
    const { run: handleDebounceFilter } = useDebounceFn(handleFilter, { wait: 300 })
    const isExternalFilterPresent = useMemoizedFn<NonNullable<ICusAgGridProps['isExternalFilterPresent']>>(() => true)
    const doesExternalFilterPass = useMemoizedFn<
      NonNullable<ICusAgGridProps<IChannelListItem>['doesExternalFilterPass']>
    >(node => {
      const { data } = node
      const channelName = filterValueRef.current.channelName.trim()
      const { firstLine, onlySelected } = filterValueRef.current
      if (channelName || firstLine != null || onlySelected) {
        let hitChannelName = true
        let hitFirstLine = true
        if (channelName) {
          hitChannelName = !!data?.channelName?.toLocaleLowerCase().includes(channelName.toLocaleLowerCase())
        }
        if (firstLine != null) {
          hitFirstLine = data?.firstLine === firstLine
        }
        return hitChannelName && hitFirstLine && (onlySelected ? !!node.isSelected() : true)
      }
      return true
    })

    // 固定行勾选列 & 初始化标识
    const onGridReady = useMemoizedFn<NonNullable<ICusAgGridProps<IChannelListItem>['onGridReady']>>(({ api }) => {
      api.setColumnsPinned([api.getColumnState()[0].colId], 'left')
      setGridReadyFlag(true)
    })

    // 请求数据
    const { loading, data: { list = [] } = {} } = useChannels()
    useEffect(() => {
      if (!gridReadyFlag) return
      const gridApi = gridRef.current?.api
      const initialSelectInfo: Record<number, string | undefined> = initialSelectRowsRef.current.reduce(
        (o, i) => ({ ...o, [i.channelId]: i.keepDate }),
        {},
      )
      const selectedIds: number[] = []
      const data: IChannelListItem[] = []
      list.forEach(d => {
        const keepDate = initialSelectInfo[d.channelId] || ''
        if (d.channelId in initialSelectInfo) selectedIds.push(d.channelId)
        data.push({ ...d, keepDate })
      })
      gridApi?.applyTransaction({ add: data })
      selectedIds.forEach(id => {
        const node = gridApi?.getRowNode(id + '')
        node?.setSelected(true)
      })
      validate() // 触发校验
      return () => {
        if (gridApi?.isDestroyed()) return
        gridApi?.applyTransaction({ remove: data })
        selectedIds.forEach(id => {
          const node = gridApi?.getRowNode(id + '')
          node?.setSelected(true)
        })
      }
    }, [gridReadyFlag, list])

    return (
      <Modal
        title="添加物流渠道"
        width={1200}
        open={open}
        onCancel={onHide}
        afterOpenChange={afterOpenChange}
        okButtonProps={{ disabled: !isValid }}
        onOk={() => {
          const selectedRows = gridRef.current?.api.getSelectedRows()
          if (!selectedRows?.length) return
          if (!isValid) return
          onHide()
          onChange(selectedRows)
        }}
        footer={(_originNode, { OkBtn, CancelBtn }) => (
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <Space>
              <Button
                type="link"
                onClick={() => {
                  gridRef.current?.api.getSelectedNodes().forEach(node => node.setSelected(false))
                }}
              >
                取消选中
              </Button>
              <span>
                已选中<b>{selectedLen}</b>条
                {!!errorLen && (
                  <>
                    ，其中<b style={{ color: 'red' }}>{errorLen}</b>条校验不通过
                  </>
                )}
              </span>
            </Space>
            <Space>
              <CancelBtn />
              <OkBtn />
            </Space>
          </div>
        )}
      >
        <Space style={{ marginBottom: 8 }} size={15}>
          <Space>
            渠道名称
            <Input
              style={{ width: 224 }}
              allowClear
              placeholder="请输入渠道名称"
              value={filterValueRef.current.channelName}
              onChange={e => {
                filterValueRef.current = { ...filterValueRef.current, channelName: e.target.value.trim() }
                update()
                handleDebounceFilter()
              }}
            />
          </Space>
          <Space>
            头程运输方式
            <Select<number>
              style={{ width: 180 }}
              allowClear
              placeholder="请选择头程运输方式"
              options={getFirstLineName.valueList.map(v => ({ label: getFirstLineName(v), value: v }))}
              value={filterValueRef.current.firstLine}
              onChange={v => {
                filterValueRef.current = { ...filterValueRef.current, firstLine: v }
                update()
                handleFilter()
              }}
            />
          </Space>
          <Checkbox
            checked={filterValueRef.current.onlySelected}
            onChange={e => {
              filterValueRef.current = { ...filterValueRef.current, onlySelected: e.target.checked }
              update()
              handleFilter()
            }}
          >
            仅显示已选中
          </Checkbox>
          <Button
            onClick={() => {
              filterValueRef.current = { channelName: '', firstLine: null, onlySelected: false }
              update()
              handleFilter()
            }}
          >
            重置
          </Button>
        </Space>
        <div style={{ height: 500 }}>
          <CusAgGrid<IChannelListItem>
            ref={gridRef}
            loading={loading}
            getRowId={undefined}
            defaultColDef={defaultColDef}
            columnDefs={columnDefs}
            rowSelection={rowSelection}
            onRowSelected={onRowSelected}
            cellSelection={cellSelection}
            onCellValueChanged={onCellValueChanged}
            isExternalFilterPresent={isExternalFilterPresent}
            doesExternalFilterPass={doesExternalFilterPass}
            onGridReady={onGridReady}
          />
        </div>
      </Modal>
    )
  },
  {
    open: (props: IAddChannelModalProps) => {
      updatePopup(<AddChannelModal {...props} destroy={() => updatePopup(null)} />)
    },
  },
)
